﻿namespace AddressBook.Business.Contact
{
	#region "Using Statements"
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Text;

	using Csla;
	using Csla.Data;
	using Csla.Validation;

  using AddressBook.Business.Person;
	#endregion

	[Serializable]
	public class ContactPhoneNumber : BusinessBase<ContactPhoneNumber>
	{
		#region "Business Methods"

		#region "Private Static Variables"

    private static PropertyInfo<Int32> PhoneNumberIdProperty = RegisterProperty<Int32>(p => p.PhoneNumberId);
    private static PropertyInfo<Int32> ContactIdProperty = RegisterProperty<Int32>(p => p.ContactId);
    private static PropertyInfo<String> PhoneNumberProperty = RegisterProperty<String>(p => p.PhoneNumber);
    private static PropertyInfo<Int32> PhoneNumberTypeIdProperty = RegisterProperty<Int32>(p => p.PhoneNumberTypeId);
    private static PropertyInfo<SmartDate> ModifiedDateProperty = RegisterProperty<SmartDate>(p => p.ModifiedDate);

		#endregion

		#region "Public Properties"

    public Int32 PhoneNumberId
    {
      get { return GetProperty(PhoneNumberIdProperty); }
      internal set { LoadProperty(PhoneNumberIdProperty, value); }
    }

    public Int32 ContactId
    {
      get { return GetProperty(ContactIdProperty); }
      internal set { LoadProperty(ContactIdProperty, value); }
    }

    public String PhoneNumber
    {
      get { return GetProperty(PhoneNumberProperty); }
      set { SetProperty(PhoneNumberProperty, value); }
    }

    public Int32 PhoneNumberTypeId
    {
      get { return GetProperty(PhoneNumberTypeIdProperty); }
      set { SetProperty(PhoneNumberTypeIdProperty, value); }
    }

    public String ModifiedDate
    {
      get { return GetProperty(ModifiedDateProperty).ToString(); }
    }

		public String FormattedPhoneNumber
		{
			get { return Person.PhoneNumber.FormatPhone(GetProperty(PhoneNumberProperty)); }
		}

		public String DisplayPhoneNumber
		{
			get
			{
				using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
				{
					var type = ctx.DataContext.PhoneNumberTypes.FirstOrDefault(pt => pt.Id == this.PhoneNumberTypeId);
					return String.Format("{0} phone - {1}", type.Name, this.FormattedPhoneNumber);
				}
			}
		}

		#endregion

		#endregion

		#region "Business Rules"

		protected override void AddBusinessRules()
		{
			ValidationRules.AddRule(CommonRules.StringRequired, new RuleArgs(PhoneNumberProperty));
			ValidationRules.AddRule(CommonRules.StringMaxLength, new CommonRules.MaxLengthRuleArgs(PhoneNumberProperty, 10));

			ValidationRules.AddRule(CommonRules.IntegerMinValue, new CommonRules.IntegerMinValueRuleArgs(PhoneNumberTypeIdProperty, 1));
		}

		#endregion

		#region "Factory Methods"

		internal static ContactPhoneNumber NewPhoneNumber(Int32 phoneNumberTypeId)
		{
			return DataPortal.CreateChild<ContactPhoneNumber>(phoneNumberTypeId);
		}

		internal static ContactPhoneNumber NewPhoneNumber(String phoneNumber, Int32 phoneNumberTypeId)
		{
			return DataPortal.CreateChild<ContactPhoneNumber>(phoneNumber, phoneNumberTypeId);
		}

		internal static ContactPhoneNumber GetPhoneNumber(AddressBook.Business.Model.ContactPhoneNumber data)
		{
			return DataPortal.FetchChild<ContactPhoneNumber>(data);
		}

    private ContactPhoneNumber()
		{ /* require use of factory methods */ }

		#endregion

		#region "Data Access"

    protected override void Child_Create()
    {

    }

    private void Child_Create(Int32 phoneNumberTypeId)
    {
      using (BypassPropertyChecks)
      {
        this.PhoneNumberId = 0;
        this.PhoneNumber = String.Empty;
        this.PhoneNumberTypeId = phoneNumberTypeId;
      }
    }

    private void Child_Create(String phoneNumber, Int32 phoneNumberTypeId)
    {
      using (BypassPropertyChecks)
      {
        this.PhoneNumberId = 0;
        this.PhoneNumber = phoneNumber;
        this.PhoneNumberTypeId = phoneNumberTypeId;
      }
    }

    private void Child_Fetch(AddressBook.Business.Model.ContactPhoneNumber data)
    {
      using (BypassPropertyChecks)
      {
        this.PhoneNumberId = data.PhoneNumberId;
        this.ContactId = data.ContactId;
        this.PhoneNumber = data.PhoneNumber.PhoneNumber1;
        this.PhoneNumberTypeId = data.PhoneNumberTypeId;

        LoadProperty(ModifiedDateProperty, data.ModifiedDate);
      }
    }

    private void Child_Insert(Contact contact)
    {
      using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
      {
        // insert contact address data
        using (BypassPropertyChecks)
        {
          AddressBook.Business.Model.ContactPhoneNumber phoneNumber = new AddressBook.Business.Model.ContactPhoneNumber();

          this.PhoneNumberId = Person.PhoneNumber.AddPhoneNumber(this.PhoneNumber);

          phoneNumber.PhoneNumberId = this.PhoneNumberId;
          phoneNumber.ContactId = contact.Id;
          phoneNumber.PhoneNumberTypeId = this.PhoneNumberTypeId;
          phoneNumber.ModifiedDate = System.DateTime.Now;

          ctx.DataContext.ContactPhoneNumbers.InsertOnSubmit(phoneNumber);
          ctx.DataContext.SubmitChanges();
        }
      }
    }

    private void Child_Update()
    {
      using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
      {
        // update contact address data
        using (BypassPropertyChecks)
        {
          AddressBook.Business.Model.ContactPhoneNumber phoneNumber = ctx.DataContext.ContactPhoneNumbers.First(p => p.PhoneNumberId == this.PhoneNumberId && p.ContactId == this.ContactId);

          Person.PhoneNumber.UpdatePhoneNumber(this.PhoneNumberId, this.PhoneNumber);

          phoneNumber.PhoneNumberId = this.PhoneNumberId;
          phoneNumber.ContactId = this.ContactId;
          phoneNumber.PhoneNumberTypeId = this.PhoneNumberTypeId;
          phoneNumber.ModifiedDate = System.DateTime.Now;

          ctx.DataContext.SubmitChanges();
        }
      }
    }

    private void Child_DeleteSelf(Contact contact)
    {
      using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
      {
        int phoneNumberId = this.PhoneNumberId;
        AddressBook.Business.Model.ContactPhoneNumber emailAddress = ctx.DataContext.ContactPhoneNumbers.First(p => p.PhoneNumberId == this.PhoneNumberId && p.ContactId == this.ContactId);

        ctx.DataContext.ContactPhoneNumbers.DeleteOnSubmit(emailAddress);
        ctx.DataContext.SubmitChanges();

        Person.PhoneNumber.RemovePhoneNumber(phoneNumberId);
      }
    }

		#endregion
	}
}